package crawer.test;

import java.io.*;
import java.util.*;

import org.apache.http.Header;
import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.message.BasicHeader;
import org.apache.http.util.EntityUtils;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;

public class Team {
    public static void main(String[] args) throws Exception {
        //读取配置文件
        Properties prop = new Properties();
        prop.load(new FileInputStream("resources//config.properties"));
        Enumeration fileName = prop.propertyNames();


        //目标主页url和学生列表url
        String urlIndex = prop.getProperty("url");
        String urlStudent = prop.getProperty("urlStudent");


        //设置cookie
        Map<String, String> header = new HashMap<String, String>();
        header.put("Cookie", prop.getProperty("cookie"));


        //直接爬取网页信息
        String indexResult = httpGet(urlIndex, null, header);
        String studentList = httpGet(urlStudent, null, header);


        //创建两张哈希表用于存储学生和多个活动页面
        Set<Student> setStudentList = new HashSet<>();
        Set<String> setEventsList = new HashSet<>();


        //开始处理已经爬取到的信息
        try {
            //获取学生列表
            setStudentList = getStudentNameList(studentList, setStudentList);


            //获取活动列表并从活动列表中筛选出课堂完成部分的所有url地址
            setEventsList = getEventListURLS(indexResult, setEventsList);


            //对课堂完成部分的所有url地址分别爬取，并解析得分，累加经验值
            for (String s : setEventsList) {
                String indexSingleEvent = httpGet(s, null, header);
                setStudentList = getSingleEventScore(indexSingleEvent, setStudentList);
            }


            //将HashSet转为ArrayList，并排序
            final ArrayList arrayListStudentList = new ArrayList(setStudentList);
            Collections.sort(arrayListStudentList);


            //算出最高值最低值和平均值
            Student s = new Student();
            double mid = 0;
            int min = 50;
            int max = 50;
            for (Iterator iter1 = arrayListStudentList.iterator(); iter1.hasNext(); ) {
                s = (Student) iter1.next();
                int temp = s.getScore();
                mid += temp;
                if (temp >= max) {
                    max = temp;
                } else if (temp <= min) {
                    min = temp;
                }
            }
            mid = mid / arrayListStudentList.size();
            mid = ((int) (mid * 100)) / 100;


            //开始往txt里写数据
            String s1 = "最高经验值:" + max + ", 最低经验值: " + min + ", 平均经验值: " + mid;
            FileWriter fw = new FileWriter("score.txt");
            BufferedWriter bw = new BufferedWriter(fw);
            bw.write(s1);
            bw.newLine();


            //输出三个值
            System.out.println("最高经验值:" + max + ", 最低经验值: " + min + ", 平均经验值: " + mid);


            //往txt中写入数据，控制台输出排名
            for (Iterator iter = arrayListStudentList.iterator(); iter.hasNext(); ) {
                String s2 = iter.next().toString();
                bw.write(s2);
                bw.newLine();
            System.out.printf("%s\n", s2);
            }
            bw.close();
        } catch (Exception e) {
            e.printStackTrace();
        }
    }



    /**
     * 发送 get 请求,爬取html信息并返回
     */
    public static String httpGet(String url, String encode, Map<String, String> headers) {
        if (encode == null) {
            encode = "utf-8";
        }
        String content = null;
        CloseableHttpClient httpclient = HttpClients.createDefault();
        HttpGet httpGet = new HttpGet(url);
        //设置 header
        Header headerss[] = buildHeader(headers);
        if (headerss != null && headerss.length > 0) {
            httpGet.setHeaders(headerss);
        }
        HttpResponse http_response;
        try {
            http_response = httpclient.execute(httpGet);
            HttpEntity entity = http_response.getEntity();
            content = EntityUtils.toString(entity, encode);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            httpGet.releaseConnection();
        }
        return content;
    }



    /**
     * 组装请求头
     */
    public static Header[] buildHeader(Map<String, String> params) {
        Header[] headers = null;
        if (params != null && params.size() > 0) {
            headers = new BasicHeader[params.size()];
            int i = 0;
            for (Map.Entry<String, String> entry : params.entrySet()) {
                headers[i] = new BasicHeader(entry.getKey(), entry.getValue());
                i++;
            }
        }
        return headers;
    }



    /**
     * 获取学生名单存入set表并返回
     */
    public static Set<Student> getStudentNameList(String s, Set<Student> set) throws Exception {
        //写入学生名单页面html
        File file = new File("src//studentList.html");
        OutputStream out = new FileOutputStream(file);
        byte[] data = s.getBytes();
        out.write(data);
        out.close();
        //解析学生名单页面html
        Document document = Jsoup.parse(file, "UTF-8");
        Elements es = document.getElementsByAttributeValue("class", "full-name");
        Elements es2 = document.getElementsByAttributeValue("class", "members-list-data").first().getElementsByAttributeValue("class", "student-no");
        for (int i = 0; i < es.size() - 3; i++) {
            //学生姓名
            String name = es.get(i + 1).text().toString();
            //学生学号
            int number = new Scanner(es2.get(i).text()).nextInt();
            set.add(new Student(number, name, 0));
        }
        return set;
    }



    /**
     * 从活动列表界面查找出所有课堂完的URL值存入set表并返回
     */
    public static Set<String> getEventListURLS(String s, Set<String> set) throws Exception {
        File file = new File("src//eventList.html");
        OutputStream out = new FileOutputStream(file);
        byte[] data = s.getBytes();
        out.write(data);
        out.close();
        Document document = Jsoup.parse(file, "UTF-8");
        Elements es1 = document.getElementsByAttributeValue("class", "interaction-rows");
        for (Element element1 : es1) {
            Elements es2 = element1.getElementsByAttributeValue("class", "interaction-row");
            for (Element element2 : es2) {
                if (element2.toString().contains("课堂完成部分")) {
                    set.add(element2.attr("data-url"));
                }
            }
        }
        return set;
    }



    /**
     * 查找单次活动中每个同学获得的分值
     */
    public static Set<Student> getSingleEventScore(String s, Set<Student> setStudentList) throws Exception {
        //创建单次活动的html文件
        File file = new File("src//singleEvent.html");
        OutputStream out = new FileOutputStream(file);
        byte[] data = s.getBytes();
        out.write(data);
        out.close();
        //使用jsoup查找分值并统计
        Document document = Jsoup.parse(file, "UTF-8");
        Elements es = document.getElementsByAttributeValue("class", "homework-item");
        for (int i = 0; i < es.size(); i++) {
            if (!es.get(i).toString().contains("未提交")) {
                //名字查找
                String name = es.get(i).select("span").get(0).text().toString();
                //分值查找
                if (es.get(i).getElementsByAttributeValue("class", "appraised-box cl").select("span").get(3).toString().contains("尚无评分")) {
                    continue;
                }
                int score = new Scanner(es.get(i).getElementsByAttributeValue("class", "appraised-box cl").select("span").get(3).text()).nextInt();
                //赋值开始
                for (Student student : setStudentList) {
                    if (student.getName().toString().equals(name)) {
                        student.setScore(student.getScore() + score);
                    }
                }
            } else
                continue;
        }
        return setStudentList;
    }
}